macro(ZHD_ADD_EXECUTABLE )
cmake_parse_arguments(
    PARSED_ARGS # prefix of output variables
    "" # list of names of the boolean arguments (only defined ones will be true)
    "TARGET;DESTINATION" # list of names of mono-valued arguments
    "SRCS;LIBDIR;LIBS;INCLUDES" # list of names of multi-valued arguments (output variables are lists)
    ${ARGN} # arguments of the function to parse, here we take the all original ones
)
# note: if it remains unparsed arguments, here, they can be found in variable PARSED_ARGS_UNPARSED_ARGUMENTS
if(NOT PARSED_ARGS_TARGET)
    message(FATAL_ERROR "You must provide a target")
endif()
set ( TARGET_NAME ${PARSED_ARGS_TARGET})
if(PARSED_ARGS_LIBDIR)
    link_directories(${TARGET_NAME} ${PARSED_ARGS_LIBDIR})
    message(STATUS "PARSED_ARGS_LIBDIR:" ${PARSED_ARGS_LIBDIR})
endif()
add_executable(${TARGET_NAME} ${PARSED_ARGS_SRCS})
message(STATUS "TARGET_NAME:" ${TARGET_NAME})
if(PARSED_ARGS_DESTINATION)
set_target_properties(${TARGET_NAME}
    PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${PARSED_ARGS_DESTINATION}"
    LINK_FLAGS "${TOOL_CHAIN_LINK_FLAG}"
    message(STATUS "PARSED_ARGS_DESTINATION:" ${PARSED_ARGS_DESTINATION})
)
endif()
if(PARSED_ARGS_LIBS)
    target_link_libraries(${TARGET_NAME} ${PARSED_ARGS_LIBS})
    message(STATUS "PARSED_ARGS_LIBS:" ${PARSED_ARGS_LIBS})
endif()
if (PARSED_ARGS_INCLUDES)
    target_include_directories(${TARGET_NAME} PUBLIC ${PARSED_ARGS_INCLUDES})
    message(STATUS "PARSED_ARGS_INCLUDES:" ${PARSED_ARGS_INCLUDES})
endif()
install(TARGETS ${TARGET_NAME}
    EXPORT ${TARGET_NAME}-target
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
)
endmacro(ZHD_ADD_EXECUTABLE)

macro(ZHD_ADD_LIBRARY )
cmake_parse_arguments(
    PARSED_ARGS # prefix of output variables
    "" # list of names of the boolean arguments (only defined ones will be true)
    "TARGET;DESTINATION" # list of names of mono-valued arguments
    "SRCS;LIBDIR;LIBS;INCLUDES" # list of names of multi-valued arguments (output variables are lists)
    ${ARGN} # arguments of the function to parse, here we take the all original ones
)
# note: if it remains unparsed arguments, here, they can be found in variable PARSED_ARGS_UNPARSED_ARGUMENTS
if(NOT PARSED_ARGS_TARGET)
    message(FATAL_ERROR "You must provide a target")
endif()
set ( TARGET_NAME ${PARSED_ARGS_TARGET})
message(STATUS "TARGET_NAME:" ${TARGET_NAME})
if(PARSED_ARGS_LIBDIR)
    link_directories(${TARGET_NAME} ${PARSED_ARGS_LIBDIR})
    message(STATUS "PARSED_ARGS_LIBDIR:" ${PARSED_ARGS_LIBDIR})
endif()
if(PARSED_ARGS_DESTINATION STREQUAL "static_lib")
    add_library(${TARGET_NAME} STATIC ${PARSED_ARGS_SRCS})
else()
    add_library(${TARGET_NAME} SHARED ${PARSED_ARGS_SRCS})
    install(TARGETS ${TARGET_NAME} EXPORT ${TARGET_NAME}-target
      RUNTIME DESTINATION bin
      LIBRARY DESTINATION lib
      ARCHIVE DESTINATION lib
    )
endif()
if(PARSED_ARGS_DESTINATION)
set_target_properties(${TARGET_NAME}
    PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${PARSED_ARGS_DESTINATION}"
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${PARSED_ARGS_DESTINATION}"
)
endif()
if(PARSED_ARGS_LIBS)
    target_link_libraries(${TARGET_NAME} ${PARSED_ARGS_LIBS})
    message(STATUS "PARSED_ARGS_LIBS:" ${PARSED_ARGS_LIBS})
endif()
if (PARSED_ARGS_INCLUDES)
    target_include_directories(${TARGET_NAME} PUBLIC ${PARSED_ARGS_INCLUDES})
    message(STATUS "PARSED_ARGS_INCLUDES:" ${PARSED_ARGS_INCLUDES})
endif()

endmacro(ZHD_ADD_LIBRARY)

macro(ZHD_COPY_FILE)
cmake_parse_arguments(
    PARSED_ARGS # prefix of output variables
    "" # list of names of the boolean arguments (only defined ones will be true)
    "FILES;DESTINATION" # list of names of mono-valued arguments
    "SRCS;LIBS;INCLUDES" # list of names of multi-valued arguments (output variables are lists)
    ${ARGN} # arguments of the function to parse, here we take the all original ones
)
# note: if it remains unparsed arguments, here, they can be found in variable PARSED_ARGS_UNPARSED_ARGUMENTS
if(NOT PARSED_ARGS_FILES)
    message(FATAL_ERROR "You must make sure which file to copy")
endif()

if(NOT PARSED_ARGS_DESTINATION)
    message(FATAL_ERROR "You must make sure which dir copy to")
endif()
message(STATUS install PROGRAMS ${PARSED_ARGS_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/${PARSED_ARGS_DESTINATION})

file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${PARSED_ARGS_DESTINATION})
add_custom_target (
    ${PARSED_ARGS_DESTINATION}
    ALL
    COMMAND cp -r ${PARSED_ARGS_FILES} ${CMAKE_INSTALL_PREFIX}/${PARSED_ARGS_DESTINATION}/
)

endmacro(ZHD_COPY_FILE)

MACRO(SUBDIRLIST Result CurrentDir)
    FILE(GLOB children ${CurrentDir}/*)
    SET(DirNameList, "")
    FOREACH(child ${children})
        IF(IS_DIRECTORY ${child})
            get_filename_component(DirName ${child} NAME)
            LIST(APPEND DirNameList ${DirName})
        ENDIF()
    ENDFOREACH()
    set(${Result} ${DirNameList})
ENDMACRO()

macro(ZHD_RUN_SCRIPT)
cmake_parse_arguments(
    PARSED_ARGS # prefix of output variables
    "" # list of names of the boolean arguments (only defined ones will be true)
    "FUNC;SCRIPT;PARAMS" # list of names of mono-valued arguments
    "SRCS;LIBS;INCLUDES" # list of names of multi-valued arguments (output variables are lists)
    ${ARGN} # arguments of the function to parse, here we take the all original ones
)
# note: if it remains unparsed arguments, here, they can be found in variable PARSED_ARGS_UNPARSED_ARGUMENTS
if(NOT PARSED_ARGS_SCRIPT)
    message(FATAL_ERROR "You must enter script_path.")
endif()

add_custom_target (
    ${PARSED_ARGS_FUNC}
    ALL
    COMMAND ${PARSED_ARGS_SCRIPT} ${PARSED_ARGS_PARAMS}
)

endmacro(ZHD_RUN_SCRIPT)


function(strip_and_save_symbols target_name)
    # 确保 CROSS_COMPILER 和 SYMBOL_OUTPUT_DIR 已经被定义
    if(NOT CROSS_COMPILER OR NOT SYMBOL_OUTPUT_DIR)
        message(FATAL_ERROR "CROSS_COMPILER and SYMBOL_OUTPUT_DIR must be defined before calling add_strip_symbols_command.")
    endif()
    # 创建符号输出目录
    file(MAKE_DIRECTORY "${SYMBOL_OUTPUT_DIR}")

    add_custom_command(TARGET ${target_name} POST_BUILD
        COMMAND "${CROSS_COMPILER}objcopy" --only-keep-debug "$<TARGET_FILE:${target_name}>" "${SYMBOL_OUTPUT_DIR}/$<TARGET_FILE_NAME:${target_name}>.stripinfo"
        COMMAND "${CROSS_COMPILER}strip" -s "$<TARGET_FILE:${target_name}>"
        COMMAND "${CROSS_COMPILER}objcopy" --add-gnu-debuglink="${SYMBOL_OUTPUT_DIR}/$<TARGET_FILE_NAME:${target_name}>.stripinfo" "$<TARGET_FILE:${target_name}>"
        COMMAND echo "Verifying stripping:"
        COMMAND "file" "$<TARGET_FILE:${target_name}>"
        COMMENT "Stripping $<TARGET_FILE_NAME:${target_name}> and saving symbols to ${SYMBOL_OUTPUT_DIR}"
    )
endfunction()
